package org.asg.dis.service;

import jakarta.validation.constraints.NotNull;
import org.asg.dis.model.ExpressStation;
import org.asg.dis.model.ExpressStationGeo;
import org.asg.dis.model.ExpressStationStatus;
import org.asg.dis.repository.ExpressStationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

@Service
public class ExpressStationService {
    private static final String STATION_GEO_PREFIX = "station:geo:"; // Redis key 前缀
    @Autowired
    private ExpressStationRepository expressStationRepository;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 在缓存中查找最接近的快递营业厅
    public void assignShipment(@NotNull String currentLocation) {
        String[] userCoords = currentLocation.split(",");
        double userLat = Double.parseDouble(userCoords[0]);
        double userLng = Double.parseDouble(userCoords[1]);

        Optional<ExpressStationGeo> nearestStationGeo = findNearestStation(userLat, userLng);

        if (nearestStationGeo.isPresent()) {
            Optional<ExpressStation> nearestStation = expressStationRepository.findById(
                    nearestStationGeo.get().getId()
            );
            nearestStation.ifPresent(this::assignToStation);
        } else {
            // TODO: 处理没有找到营业厅的情况
            System.out.println("没有找到可用的快递营业厅。");
        }
    }

    // 查找最近的站点，尝试从缓存中查找站点地理位置信息
    private Optional<ExpressStationGeo> findNearestStation(double userLat, double userLng) {
        ExpressStationGeo nearest = null;
        double minDistance = Double.MAX_VALUE;

        for (ExpressStationGeo station : getAllExpressStations()) {
            String stationGeo = (String) redisTemplate.opsForValue().get(STATION_GEO_PREFIX + station.getId());

            if (stationGeo != null) {
                String[] stationCoords = stationGeo.split(",");
                double stationLat = Double.parseDouble(stationCoords[0]);
                double stationLng = Double.parseDouble(stationCoords[1]);

                double distance = calculateDistance(userLat, userLng, stationLat, stationLng);
                if (distance < minDistance) {
                    minDistance = distance;
                    nearest = station;
                }
            }
        }

        return Optional.ofNullable(nearest);
    }

    // 从 Redis 获取所有快递站点的缓存信息
    private List<ExpressStationGeo> getAllExpressStations() {
        List<ExpressStationGeo> stations = new ArrayList<>();
        Set<String> keys = redisTemplate.keys(STATION_GEO_PREFIX + "*");

        if (keys != null) {
            for (String key : keys) {
                ExpressStationGeo station = (ExpressStationGeo) redisTemplate.opsForValue().get(key);
                if (station != null) {
                    stations.add(station);
                }
            }
        }
        return stations;
    }
    public List<ExpressStation> getAll(){
        return expressStationRepository.findAll();
    }
    // 将派送任务分配给指定的营业厅
    private void assignToStation(ExpressStation station) {
        //TODO 具体派件
        System.out.println("快递派送到：" + station.getName());
    }

    // 计算两点之间的距离（使用 Haversine 公式）
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int R = 6371; // 地球半径，单位为公里
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c; // 返回距离（公里）
    }

    // 将所有站点的地理位置信息存入 Redis
    public void cacheGeo() {
        List<ExpressStationGeo> stations = expressStationRepository.findAllStationGeo();
        for (ExpressStationGeo station : stations) {
            String key = STATION_GEO_PREFIX + station.getId();
            String value = station.getCoordinate();
            redisTemplate.opsForValue().set(key, value);  // 存入 Redis
        }
    }

    public void addExpressStation(ExpressStation station) {
        expressStationRepository.save(station);
    }

    public void modifyExpressStation(Long id, ExpressStation station) {
        Optional<ExpressStation> existingStation = expressStationRepository.findById(id);

        if (existingStation.isPresent()) {
            ExpressStation updatedStation = existingStation.get();

            if (station.getName() != null) {
                updatedStation.setName(station.getName());
            }
            if (station.getLocation() != null) {
                updatedStation.setLocation(station.getLocation());
            }

            expressStationRepository.save(updatedStation);
        } else {
            throw new RuntimeException("未找到指定的营业厅");
        }

    }

    public void deleteExpressStation(Long id) {
        int updatedCount = expressStationRepository.updateStatus(id, ExpressStationStatus.关停);

        if (updatedCount == 0) {
            throw new RuntimeException("未找到指定的营业厅");
        }
    }
}

